from pathlib import Path

from vulcanus.log.log import LOGGER
from vulcanus.restful.response import BaseResponse
from vulcanus.restful.resp.state import SUCCEED, DATABASE_UPDATE_ERROR, NO_DATA

from zeus.operation_service.app.constant import DATA_COLLECT_PATH
from zeus.operation_service.app.serialize.task import GetTaskSchema, AddTaskSchema, TaskSchema, ModifyTaskSchedulerSchema
from zeus.operation_service.app.proxy.task import TaskProxy
from zeus.operation_service.app.core.task_manager import TaskManager
from zeus.operation_service.app.core.framework.task.task_result.task_result_context import TaskResultContext
from zeus.operation_service.app.core.framework.task.task_result.data_collect_task_result_detail import DataCollectResultDetail
from zeus.operation_service.app.core.framework.common.constant import TaskType
from zeus.operation_service.app.core.asset.tools.file_response import build_file_response
from flask import request,g


class TaskManageAPI(BaseResponse):
    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def get(self, callback: TaskProxy, **params):
        task_id = params.get('task_id', None)
        if task_id and task_id is not None:
            status_code, task, host_ids = callback.get_task_info(task_id)
            if task:
                if task.task_type == TaskType.HEALTH_CHECK or task.task_type == TaskType.DATA_COLLECT \
                        or task.task_type == TaskType.SECURITY_MANAGE:
                    result = TaskResultContext(task).generate_hosts_assets()
                else:
                    result = TaskSchema().dump(task)
                    result['host_ids'] = host_ids
        else:
            status_code, result = callback.get_tasks(params)
        return self.response(code=status_code, data=result)

    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def post(self, callback: TaskProxy, **params):
        action = params.get('action', None)
        if action and action is not None:
            task_id = params.get('task_id')
            task_mng = TaskManager()
            LOGGER.info(f"task {task_id}, action: {action}")
            status_code, result = task_mng.do_action(task_id, action)
        else:
            status_code, result = callback.add_task(params)
        return self.response(code=status_code, data=result)

    @BaseResponse.handle(schema=ModifyTaskSchedulerSchema, proxy=TaskProxy, token=False)
    def patch(self, callback: TaskProxy, **params):
        status_code = callback.modify_task_scheduler(params)
        return self.response(code=status_code)
    
    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def delete(self, callback: TaskProxy, **params):
        task_id = params.get('task_id', None)
        if task_id and task_id is not None:
            task_ids = [task_id]
        else:
            task_ids = params['task_ids']
        status_code, result = callback.batch_delete_task(task_ids)
        return self.response(code=status_code, data=result)


class TaskInfoManageAPI(BaseResponse):
    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def get(self, callback: TaskProxy, task_id, **params):
        status_code, task, host_ids = callback.get_task_info(task_id)
        if task:
            if task.task_type == TaskType.HEALTH_CHECK or task.task_type == TaskType.DATA_COLLECT \
                    or task.task_type == TaskType.SECURITY_MANAGE:
                result = TaskResultContext(task).generate_hosts_assets()
            else:
                result = TaskSchema().dump(task)
                result['host_ids'] = host_ids
        return self.response(code=status_code, data=result)
    
    @BaseResponse.handle(token=False)
    def post(self, task_id):
        action = request.args.get('action')
        task_mng = TaskManager()
        LOGGER.info(f"task {task_id}, action: {action}")
        code, result = task_mng.do_action(task_id, action)
        return self.response(code=code, data=result)

    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def patch(self, callback: TaskProxy, task_id, **params):
        try:
            task = callback.get_task_by_id(task_id)
            task_result = TaskResultContext(task)
            task_result.update_progress(params)
            return self.response(code=SUCCEED)
        except Exception as e:
            LOGGER.error(e)
            return self.response(code=DATABASE_UPDATE_ERROR)

    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def delete(self, callback: TaskProxy, task_id, **params):
        status_code, result = callback.batch_delete_task([task_id])
        return self.response(code=status_code, data=result)

class TaskHostItemResultAPI(BaseResponse):
    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def post(self, callback: TaskProxy, **params):
        task = callback.get_task_by_id(params["task_id"])
        task_result = TaskResultContext(task)
        code, result = task_result.get_items_detail(params)
        return self.response(code=code, data=result)


class TaskResultDownloadAPI(BaseResponse):
    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def get(self, callback: TaskProxy, task_id, **params):
        try:
            task = callback.get_task_by_id(task_id)
            task_result = TaskResultContext(task)
            result = task_result.download_task_result()
            return build_file_response(result)
        except Exception as e:
            LOGGER.error(e)
            return self.response(code=DATABASE_UPDATE_ERROR)

    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def post(self, callback: TaskProxy, task_id, **params):
        try:
            task = callback.get_task_by_id(task_id)
            task_result = DataCollectResultDetail(task)
            result = task_result.download_single_item_result(params)
            return build_file_response(result)
        except Exception as e:
            LOGGER.error(e)
            return self.response(code=DATABASE_UPDATE_ERROR)


class TaskResultAPI(BaseResponse):
    @BaseResponse.handle(proxy=TaskProxy, token=False)
    def post(self, callback: TaskProxy, **params):
        task = callback.get_task_by_id(params["task_id"])
        task_result = DataCollectResultDetail(task)
        code, result = task_result.get_item_result(params)
        return self.response(code=code, data=result)


class LogGPTResultAPI(BaseResponse):
    @BaseResponse.handle(token=False)
    def post(self, **params):
        task_id = params.get('task_id')
        host_ip = params.get('host_ip')
        log_type = params.get('log_type')
        root_path = Path(DATA_COLLECT_PATH).resolve().joinpath(task_id)
        if not (root_path.exists() and root_path.is_dir()):
            return self.response(code=NO_DATA, data={})
        dst_file = None
        for path in root_path.iterdir():
            if path.name.startswith(f"{host_ip}_"):
                for dst_path in path.rglob("logGPT"):
                    file = dst_path.joinpath(f"{log_type}.txt")
                    dst_file = file if file.exists() else None
                    break
                break
        if dst_file:
            data = {
                "file_name": "dmesg.txt",
                "log_type": log_type,
                "file_path": str(dst_file)
            }
            return self.response(code=SUCCEED, data=data)
        return self.response(code=NO_DATA, data={})
